/*
 * Created by zhangzxiang91@gmail.com on 2020/11/30.
 */
package com.perfma.util.tool;

import org.apache.commons.lang3.StringUtils;

import java.util.UUID;

/**
 * @author zhangzxiang91@gmail.com
 * @date 2020/11/30.
 */
public class TraceContext {

	public static final String TRACE_ID_KEY  = "traceId";
	public static final String TRACE_URL_KEY = "traceUrl";

	private static volatile TraceContext instance;

	private final ThreadLocal<Trace> traceLocal = new ThreadLocal<>();

	private TraceContext() {
	}

	public static TraceContext get() {
		if (instance == null) {
			synchronized (TraceContext.class) {
				if (instance == null) {
					instance = new TraceContext();
				}
			}
		}
		return instance;
	}

	/**
	 * 创建一个默认入口请求
	 */
	public Trace createLogTrace() {
		return createLogTrace(null);
	}

	/**
	 * 创建一个新入口的请求
	 */
	public Trace createLogTrace(String traceUrl) {
		traceLocal.set(new Trace(UUID.randomUUID().toString().replaceAll("-", ""), traceUrl));
		return getLogTrace();
	}

	/**
	 * 传递跟踪链路
	 */
	public Trace transmitLogTrace(String traceId, String traceUrl) {
		return this.transmitLogTrace(traceId, traceUrl, null);
	}

	/**
	 * 传递跟踪链路
	 */
	public Trace transmitLogTrace(String traceId, String traceUrl, String refererUrl) {
		traceLocal.set(new Trace(traceId, traceUrl, refererUrl));
		return getLogTrace();
	}

	public Trace getLogTrace() {
		return traceLocal.get() == null ? createLogTrace() : traceLocal.get();
	}

	/**
	 * 该接口主要用于开启新线程时，需要将当前线程的跟踪对象设置到新开启的线程，此时用该接口
	 */
	public void setTrace(Trace trace) {
		traceLocal.set(trace);
	}

	public void cleanTrace() {
		traceLocal.set(null);
	}

	/**
	 * 根据不同的用户请求，对应不同的跟踪标识对象
	 */
	public static class Trace {

		private final String id;
		private final String url;
		private final String referer;

		private Trace(String traceId, String traceUrl) {
			this(traceId, traceUrl, null);
		}

		public Trace(String traceId, String traceUrl, String refererUrl) {
			this.id = StringUtils.trimToEmpty(traceId);
			this.url = StringUtils.trimToEmpty(traceUrl);
			this.referer = StringUtils.trimToEmpty(refererUrl);
		}

		public String getId() {
			return id;
		}

		public String getUrl() {
			return url;
		}

		public String getReferer() {
			return referer;
		}

		@Override
		public String toString() {
			return "LogTrace{" + "id='" + id + '\'' + ", url='" + url + '\'' + ", referer='" + referer + '\'' + '}';
		}
	}
}
